<template>
  <div :class="{active:conf.show}" @click="show" @mouseleave="conf.show=false">
    <span
      v-if="conf.onClick || conf.list"
      @click="clickHandel"
      class="iconfont icon-down"
      :class="{
        val: resultName,
        dis: conf.disabled,
      }"
    >{{spanName}}</span>
    <input
      v-if="!conf.list && !conf.onClick"
      :type="conf.inputType || 'text'"
      :class="{dis: conf.disabled,}"
      :maxlength="conf.maxLength"
      v-model="conf.val"
      :placeholder="placeholderName"
    />
    <!--@change="onInput"-->
    <div v-if="conf.list && conf.list.length > 0" class="rule-select" :class="{active: conf.show && !conf.disabled}">
      <ul>
        <li
          v-for="(item, index) in conf.list"
          :key="index"
          v-if="!item.disabled"
          @click.stop="onSelect(item, conf.list)"
          :class="{active: isItemSelected(item)}"
        >
          <span>{{item.name || conf.placeholder}}</span>
          <span class="drop-check" v-if="isTypeCheck"></span>
        </li>
      </ul>
    </div>
  </div>
</template>
<script>
/**
 * 啊  我不想写注释的， 但是涅又没有单元测试，为了放置后面自己都不知道写了啥， 所以。。。。
 *  @val 用于给input 双向绑定的
 *  @type radio | check;
 *  @onClick 有时候呢，我们想给表单定义一个点击事件
 *  @list [istObj] 又有的情况i下， 我们像点击表单的时候出现个下拉框
 *  @onSelect 下单框的某项被选中时， 我们偶尔想干点其他的事
 *  @listObj.selected 当该项被选中时，我们偶尔想干点其他的事， 但是又想精确的知道哪个选项被选中（而非根据其他值去判断）
 *  @disabled 我想有时候要让这个输入框禁用掉（区分点击时的只读）
 *  @inputType 有时我们希望输入框事数字而不仅仅只能使用默认的文本
 * @show 用来标识下拉框是否展开的字段
 *  @placeholder 自定义的placeholder
 *  @name 类似于label 用于根据输入框类型（click list）拼接placeholer
 *  @isNoNeedPlaceholder 有该字段则代表无需显示placeholder
 *  @extendName 用于显示的扩展后的值 由于设置list中isActive 为true的项的name属性的优先级高于val 故提供另一个高优先级的值来覆盖list选中的值
 *  @extendVal 同extendName，区别为extendName用于展示， extendVal用于存放提交时需要使用的数据
 *  @shouldShowSelectedItemWhenExtendValueExist 当存在extendName时， 是否需要再前面拼接选中项的name
 *  listObj
 *  @istObj.id 选中值的 id|code 用于服务端传值
 *  @istObj.code 选中值的 id|code 用于服务端传值 优先级高于 id
 *  @istObj.name 选中值的 中文字符 用于客户端展示
 *  @istObj.isActive 代表改项是否被选中
 *  @istObj.onSelect 方法， 改项被选中时触发
 *  @istObj.disabled 改项是否被禁用（当前实现禁用不显示）
 * */
export default {
  name: "vuc-drop",
  props: ["conf"],
  watch: {
    conf() {
      this.inits();
    },
  },
  mounted() {
    this.inits();
  },
  computed: {
    isTypeCheck() {
      return this.conf.type === "check";
    },
    placeholderName() {
      const conf = this.conf;
      let ret = (conf.list || conf.onClick) ? "请选择" : "请输入";
      conf.name && (ret = (ret || "") + (conf.name || "") + (conf.type === "check" ? " (多选) " : ""));
      conf.placeholder && (ret = conf.placeholder || "");
      conf.isNoNeedPlaceholder && (ret = "");
      return ret;
    },
    spanName() {
      return this.resultName || this.placeholderName;
    },
    resultName() {
      const conf = this.conf;
      let ret = this.extendName;
      ret && this.selected && conf.shouldShowSelectedItemWhenExtendValueExist && (ret = (this.selected.name || "") + (ret || ""));
      ret || (ret = this.isTypeCheck ? this.selectedList.map(item => item.name || "").join(",") : (this.selected && this.selected.name || ""));
      !conf.list && !conf.onClick && !ret && (ret = conf.val || ""); // 仅当为输入框的时候才会考虑将value展示
      return ret && ("" + ret).replace(/^\s*/, "").replace(/\s*$/, "");
    },
    resultVal() {
      return (this.conf.list || this.conf.onClick) ? this.extendVal || (this.isTypeCheck ? this.selectedList.map(item => item.id).join(",") : this.selected && this.selected.id) : this.conf.val;
    },
    extendName() {
      return this.conf.extendName
    },
    extendVal() {
      return this.conf.extendVal
    },
    selected() {
      return this.selectedList && this.selectedList[0];
    },
    selectedList() {
      return this.conf.list && this.conf.list.filter(item => !item.disabled && item.isActive);
    },
  },
  methods: {
    inits() {
      this.conf.getVal = () => ({name: this.resultName, val: this.resultVal,})
    },
    isItemSelected(item) {
      return this.isTypeCheck ? this.selectedList && this.selectedList.includes(item) : item === this.selected;
    },
    clickHandel() {
      this.conf.disabled || (this.conf.onClick && this.conf.onClick(this.conf));
    },
    onSelect(item, list) {
      if (item.disabled) return;
      this.isTypeCheck ? (item.isActive = !item.isActive) :
        list.forEach(key => (key.isActive = item === key));
      item.onSelect && item.onSelect(item, list);
      this.conf.onSelect && this.conf.onSelect(item, list);
      this.isTypeCheck || (this.conf.show = false);
    },
    show() {
      this.conf.show = true;
    },
  }
}
</script>
<style scoped>
  div,
  .iconfont {
    position: relative;
  }

  .icon-down:before {
    position: absolute;
    display: block;
    right: 0;
    top: 50%;
    transform: translateY(-50%) rotate(0deg);
    transition: all .3s;
    font-size: 12px;
    margin-right: 4px;
  }

  .active > .icon-down:before {
    transform: translateY(-50%) rotate(180deg);
  }

  div.active {
    z-index: 1;
  }

  div > span,
  div > input {
    background-color: #fff;
    display: block;
    vertical-align: middle;
    width: 100%;
    border: 1px solid #ccc;
    line-height: 28px;
    min-height: 30px;
    border-radius: 5px;
    font-size: 12px;
    padding: 0 21px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: all .3s;
    box-shadow: 0 0px 0px #eee;
    text-align: left;
  }

  div > input:focus,
  div > input:hover,
  div > span:focus,
  div > span:hover {
    box-shadow: 0 5px 5px #eee;
    border: 1px solid #3385ff;
  }

  div > input.dis:focus,
  div > input.dis:hover,
  div > span.dis:focus,
  div > span.dis:hover {
    border: 1px solid #ccc;
    box-shadow: 0 0px 0px #eee;
    cursor: auto;
  }

  div > span.dis:before {
    display: none;
  }

  div > span {
    color: #999;
  }

  div > span.val {
    color: #333;
  }

  input::-webkit-outer-spin-button,
  input::-webkit-inner-spin-button {
    -webkit-appearance: none;
  }

  input[type="number"] {
    -moz-appearance: textfield;
  }

  .range-group div {

  }

  .range-group div > span,
  .range-group div > input {
    padding: 5px 30px;
    display: inline-block;
    line-height: 22px;
    white-space: normal;
    word-break: break-all;
    border-radius: 2px;
  }

  .range-group div > span:before {
    right: 15px;
  }

  .flow-rule div > span,
  .flow-rule div > input {
    display: inline-block;
    line-height: 34px;
    padding-right: 0 30px;
    font-size: 14px;
    color: #666;
    white-space: normal;
    word-break: break-all;
  }

  .flow-rule div > span.val {
    color: #333;
  }

  .setting-tree div > span,
  .setting-tree div > input {
    text-align: left;
    flex: 1 1 0;
    height: 100%;
    max-height: 80px;
    overflow: hidden;
    text-overflow: ellipsis;
    overflow-y: scroll;
  }

  .rule-select ul::-webkit-scrollbar,
  .setting-tree div > span::-webkit-scrollbar,
  .setting-tree div > input::-webkit-scrollbar {
    width: 0;
  }

  .rule-select {
    position: absolute;
    width: 100%;
    min-width: 200px;
    top: 100%;
    right: 0;
    padding-top: 0;
    overflow: hidden;
    border-radius: 0 0 4px 4px;
    height: 0;
    transition: all .3s;
    background-color: #fff;
  }
  .rule-select.active{
    height: 200px;
    padding-top: 10px;
  }
  .rule-select > ul{
    height: 100%;
    overflow-y: scroll;
    border-radius: 4px;
    border: 1px solid rgba(221, 221, 221, 1);
  }
  .rule-select > ul > * {
    width: 100%;
    padding: 0 15px;
    padding-right: 22px;
    line-height: 40px;
    color: #999;
    font-size: 12px;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
    transition: all .3s;
    box-shadow: 0 3px 7px 0 rgba(0, 0, 0, 0.09);
  }

  .rule-select > ul > *[disabled="disabled"] {
    background-color: #eee;
    cursor: not-allowed;
  }

  .rule-select > ul > li:hover {
    position: relative;
    color: #333;
    background-color: rgba(247, 247, 247, 1);;
  }

  .rule-select > ul > li.active {
    color: #3385ff;
  }

  .rule-select li {
    background-color: #fff;
    display: flex;
  }

  .rule-select li > span:first-child {
    flex: 1 1 0;
  }

  .drop-check {
    position: relative;
  }

  .drop-check:after {
    box-sizing: border-box;
    content: "";
    display: block;
    position: absolute;
    width: 8px;
    height: 4px;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) rotate(-45deg);
    border-left: 2px solid #fff;
    border-bottom: 2px solid #fff;
    transition: all .3s;
  }

  .drop-check:before {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    box-sizing: border-box;
    content: "";
    transition: all .3s;
    height: 16px;
    width: 16px;
    display: inline-block;
    color: #fff;
    border: 1px solid #999;
    border-radius: 2px;
  }

  .active > .drop-check:after {
    border-left: 2px solid #3385ff;
    border-bottom: 2px solid #3385ff;
  }

  .active > .drop-check:before {
    border: 1px solid #3385ff;
  }

  .rule-select:before {
    content: '';
    position: absolute;
    right: 20px;
    top: 5px;
    display: block;
    width: 10px;
    height: 10px;
    background-color: #fff;
    transform: rotate(45deg);
    border-left: 1px solid rgba(221, 221, 221, 1);
    border-top: 1px solid rgba(221, 221, 221, 1);
  }

</style>
